# encoding: utf-8
"""
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    created by lane.chang on '17/10/2024'
    comment: 节点项目
"""
import json
from typing import Optional
from fastapi import APIRouter, Request, Body, Query, BackgroundTasks

from config import Config
from project.core.exception import NoRecordError, BizError
from project.core.function import json_response
from project.lib.decorator import api_common, exec_duration
from project.lib.constant import DEFAULT_VALUE
from project.model.basic import NodeItemDetail, Spec
from project.model.database.node import NodeItem, Node
from project.service.common.jpush import JpushService, NODE_FLUSH
from project.service.common.mqtt import MQTTService


item_router = APIRouter(prefix='/m', tags=['manager.item'])


@item_router.post('/node/item/add', summary='新增项目')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def do_node_item_add(request: Request,
                           background_tasks: BackgroundTasks,
                           node_id: int = Body(..., title='节点id'),
                           group_id: int = Body(0, title='节点分组id'),
                           title: str = Body(..., max_length=30, title='项目标题'),
                           content: Optional[str] = Body(None, max_length=200, title='项目内容'),
                           image: Optional[str] = Body(None, max_length=500, title='项目图片'),
                           price: Optional[float] = Body(None, title='项目单价'),
                           detail: Optional[list[NodeItemDetail]] = Body(None, title='项目详情', description='{"start_time": xxx, "end_time": xxx}'),
                           count_upper_limit: int = Body(100, title='数量上限'),
                           is_count: int = Body(0, title='是否可选数量'),
                           is_spec: int = Body(0, title='是否可选规格'),
                           spec: Optional[list[Spec]] = Body(None, title='规格信息', description='[{"title": xxx, "items": [xxx, xxx, xxx]}, {"title": xxx, "items": [xxx, xxx, xxx]}]'),
                           session=None,
                           body_params=None,
                           operator=None):
    """
    **desc**: 新增节点项目

    **url**: http(s)://{0}.udicaria.com/m/node/item/add

    **method**: POST

    **params**:

        <body>:
            node_id: 节点id
            group_id: 节点分组id
            title: 项目标题
            content: 项目内容
            image: 项目图片
            price: 项目单价
            detail: 项目详情
            count_upper_limit: 数量上限
            is_count: 是否可选数量
            is_spec: 是否可选规格
            spec: 规格信息

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    item = await NodeItem.create_modify(session, **body_params.dict())

    # 极光推送
    node = await Node.fetch_one(session, wheres=(Node.id == item.node_id))
    if node:
        # 极光推送
        background_tasks.add_task(JpushService.push, session, organization_code=operator.organization_code, flow_code=node.flow_code, node_code=node.code, _type=NODE_FLUSH)
        # MQTT 推送
        background_tasks.add_task(MQTTService.push, topic=f'cariabot/{operator.organization_code}', message=json.dumps({'action': 'node_flush','flow_code': node.flow_code, 'node_code': node.code}, ensure_ascii=False).encode('utf-8'))

    return json_response(data=item.dict('id'))


@item_router.post('/node/item/update', summary='修改项目')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def do_node_item_update(request: Request,
                              background_tasks: BackgroundTasks,
                              id: int = Body(..., title='节点项目id'),
                              title: str = Body(..., max_length=30, title='项目标题'),
                              content: Optional[str] = Body(DEFAULT_VALUE, max_length=200, title='内容'),
                              image: Optional[str] = Body(DEFAULT_VALUE, max_length=500, title='图片'),
                              price: Optional[float] = Body(DEFAULT_VALUE, title='单价'),
                              detail: Optional[list[NodeItemDetail]] = Body(DEFAULT_VALUE, title='详情', description='{"start_time": xxx, "end_time": xxx}'),
                              count_upper_limit: int = Body(DEFAULT_VALUE, title='数量上限'),
                              is_count: int = Body(DEFAULT_VALUE, title='是否可选数量'),
                              is_spec: int = Body(DEFAULT_VALUE, title='是否可选规格'),
                              spec: list[Spec] = Body(DEFAULT_VALUE, title='规格信息', description='[{"title": xxx, "items": [xxx, xxx, xxx]}, {"title": xxx, "items": [xxx, xxx, xxx]}]'),
                              session=None,
                              body_params=None,
                              operator=None):
    """
    **desc**: 修改节点项目

    **url**: http(s)://{0}.udicaria.com/m/node/item/update

    **method**: POST

    **params**:

        <body>:
            id: 节点项目id
            title: 项目标题
            content: 项目内容
            image: 项目图片
            price: 项目单价
            detail: 项目详情
            count_upper_limit: 数量上限
            is_count: 是否可选数量
            is_spec: 是否可选规格
            spec: 规格信息 [{"title": xxx, "items": [xxx, xxx, xxx]}, {"title": xxx, "items": [xxx, xxx, xxx]}]

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    try:
        item = await NodeItem.create_modify(session, wheres=(NodeItem.id == id), **body_params.dict())
    except NoRecordError:
        raise BizError('节点项目不存在')

    # 极光推送
    node = await Node.fetch_one(session, wheres=(Node.id == item.node_id))
    if node:
        # 极光推送
        background_tasks.add_task(JpushService.push, session, organization_code=operator.organization_code, flow_code=node.flow_code, node_code=node.code, _type=NODE_FLUSH)
        # MQTT 推送
        background_tasks.add_task(MQTTService.push, topic=f'cariabot/{operator.organization_code}', message=json.dumps({'action': 'node_flush','flow_code': node.flow_code, 'node_code': node.code}, ensure_ascii=False).encode('utf-8'))

    return json_response()


@item_router.get('/node/item/list', summary='项目列表')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def get_node_item_list(request: Request,
                             node_id: int = Query(..., title='节点id'),
                             group_id: int = Query(0, title='节点分组id'),
                             session=None):
    """
    **desc**: 节点项目列表

    **url**: http(s)://{0}.udicaria.com/m/node/item/list

    **method**: GET

    **params**:

        <query>:
            node_id: 节点id
            group_id: 节点分组id

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: [
                {
                    id: 节点项目id
                    title: 项目标题
                    content: 项目内容
                    image: 项目图片
                    price: 项目单价
                    detail: 项目详情
                    count_upper_limit: 数量上限
                    is_count: 是否可选数量
                    is_spec: 是否可选规格
                    spec: 规格信息 [{"title": xxx, "items": [xxx, xxx, xxx]}, {"title": xxx, "items": [xxx, xxx, xxx]}]
                }
            ]
            exec_time: 接口后端处理时长
        }
    """
    wheres = list()
    wheres.append(NodeItem.node_id == node_id)
    if group_id:
        wheres.append(NodeItem.group_id == group_id)
    wheres.append(~NodeItem.is_deleted)

    data = await NodeItem.fetch_all(session,
                                    wheres=wheres,
                                    orders=(NodeItem.id,))

    return json_response(data=[v.dict() for v in data])


@item_router.get('/node/item/detail', summary='项目详情')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def get_node_item_detail(request: Request,
                               id: int = Query(..., title='节点项目id'),
                               session=None):
    """
    **desc**: 节点项目列表

    **url**: http(s)://{0}.udicaria.com/m/node/item/detail

    **method**: GET

    **params**:

        <query>:
            id: 节点项目id

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: {
                id: 节点项目id
                title: 项目标题
                content: 项目内容
                image: 项目图片
                price: 项目单价
                detail: 项目详情
                count_upper_limit: 数量上限
                is_count: 是否可选数量
                is_spec: 是否可选规格
                spec: 规格信息 [{"title": xxx, "items": [xxx, xxx, xxx]}, {"title": xxx, "items": [xxx, xxx, xxx]}]
            }
            exec_time: 接口后端处理时长
        }
    """
    item = await NodeItem.fetch_one(session, wheres=(NodeItem.id == id))

    return json_response(data=item.dict() if item else {})


@item_router.post('/node/item/delete', summary='删除项目')
@api_common(doc_replace=(('{0}', Config.ENV_DOC_FIX),), verify_login=True)
@exec_duration(add_return=True)
async def do_node_item_delete(request: Request,
                               id: int = Body(..., title='节点项目id', embed=True),
                               session=None):
    """
    **desc**: 删除节点项目

    **url**: http(s)://{0}.udicaria.com/m/node/item/delete

    **method**: POST

    **params**:

        <body>:
            id: 节点id

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    try:
        await NodeItem.create_modify(session, wheres=(NodeItem.id == id), no_record_error=True, is_deleted=1)
    except NoRecordError:
        raise BizError('节点项目')

    return json_response()
